package com.dingreading.cloud.admin.service.impl;

import com.dingreading.cloud.admin.dto.StaffDto;
import com.dingreading.cloud.admin.dto.StaffPageDto;
import com.dingreading.cloud.admin.entity.Staff;
import com.dingreading.cloud.admin.entity.table.StaffTableDef;
import com.dingreading.cloud.admin.mapper.StaffMapper;
import com.dingreading.cloud.admin.service.AdminRoleStaffService;
import com.dingreading.cloud.admin.service.StaffRolesService;
import com.dingreading.cloud.admin.service.StaffService;
import com.dingreading.cloud.admin.util.AdminStaffRoleUtil;
import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.util.PageDto;
import com.dingreading.cloud.common.util.PageUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryMethods;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.update.UpdateChain;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static com.dingreading.cloud.admin.entity.table.StaffRolesTableDef.staffRoles;


/**
 * 服务层实现。
 *
 * @author Administrator
 * @since 2023-11-22
 */
@Service
public class StaffServiceImpl extends BaseServiceImpl<StaffMapper, Staff, StaffTableDef> implements StaffService {

    @Override
    protected StaffTableDef getTable() {
        return StaffTableDef.staff;
    }

    @Resource
    private StaffMapper staffMapper;
    @Resource
    private StaffRolesService staffRolesService;
    @Resource
    private AdminRoleStaffService roleStaffService;

    @Override
    public PageDto<StaffDto> storeManagerPageList(PageUtil pageUtil, String keyword) {
        Map<String, Object> otherParams = new HashMap<>();
        otherParams.put("keyword", keyword);

        Page<StaffDto> page = getMapper().xmlPaginate("storeManagerPageList", Page.of(pageUtil.getPage(), pageUtil.getRows()), otherParams);

        long count = page.getTotalRow();
        List<StaffDto> list = page.getRecords();

        PageDto<StaffDto> data = new PageDto<>();
        data.setTotal(count);
        data.setList(list);

        return data;
    }

    @Override
    public Staff getByUid(String uid) {
        return getMapper().selectOneByCondition(table.uid.eq(uid));
    }

    @Override
    public boolean updateInfo(
            String headStaffUid, String headStaffName, String uid, String fullName, String nickName,
            String pubPhone, String priPhone, String subjectType
    ) {
        return UpdateChain.of(Staff.class)
                .set(table.fullName, StringUtils.defaultString(fullName))
                .set(table.nickName, StringUtils.defaultString(nickName))
                .set(table.pubPhone, StringUtils.defaultString(pubPhone))
                .set(table.priPhone, StringUtils.defaultString(priPhone))
                .set(table.subjectType, StringUtils.defaultString(subjectType))
                .set(table.lastStaffUid, headStaffUid)
                .set(table.lastStaffName, headStaffName)
                .where(table.uid.eq(uid))
                .update();
    }

    @Override
    public boolean updateEnabled(String headStaffUid, String headStaffName, String uid, Integer enabled) {
        return UpdateChain.of(Staff.class)
                .set(table.enabled, enabled)
                .set(table.lastStaffUid, headStaffUid)
                .set(table.lastStaffName, headStaffName)
                .where(table.uid.eq(uid))
                .update();
    }

    @Override
    public Staff getLastUsername(String corpUid) {
        QueryWrapper wrapper = QueryWrapper.create()
                .where(table.username.likeLeft(corpUid))
                .orderBy(table.id.desc());

        return getMapper().selectOneByQuery(wrapper);
    }

    @Override
    public List<StaffDto> getStoreStaffs(String storeUid, String keyword, Integer enabled) {
        QueryCondition condition = QueryCondition.createEmpty();
        condition.and(staffRoles.storeUid.eq(storeUid));
        if (StringUtils.isNotBlank(keyword))
            condition.and(table.username.like(keyword)
                    .or(table.fullName.like(keyword))
                    .or(table.nickName.like(keyword))
                    .or(table.pubPhone.like(keyword))
                    .or(table.priPhone.like(keyword)));
        if (null != enabled)
            condition.and(table.enabled.eq(enabled));

        QueryWrapper wrapper = QueryWrapper.create()
                .select(table.allColumns,
                        staffRoles.storeUid, staffRoles.roles, staffRoles.roleName,
                        staffRoles.isHeadquarterStaff.as("isHeadquarterStaff"), staffRoles.isStoreStaff.as("isStoreStaff"), staffRoles.inStoreService
                )
                .from(table)
                .leftJoin(staffRoles).on(table.uid.eq(staffRoles.staffUid))
                .where(condition)
                .orderBy(table.enabled.desc(), staffRoles.roleName.desc(), table.id.asc());

        return getMapper().selectListWithRelationsByQueryAs(wrapper, StaffDto.class);
    }

    @Override
    public int dropBean(String staffUid) {
        return getMapper().deleteByCondition(table.uid.eq(staffUid));
    }

    @Override
    public boolean resetPwd(String headStaffUid, String headStaffName, String staffUid, String encodedPwd, String pwdSalt) {
        return UpdateChain.of(Staff.class)
                .set(table.encodedPwd, encodedPwd)
                .set(table.pwdSalt, pwdSalt)
                .set(table.lastStaffUid, headStaffUid)
                .set(table.lastStaffName, headStaffName)
                .where(table.uid.eq(staffUid))
                .update();
    }


    @Override
    public List<StaffDto> getStoreManager(String keyword) {
        return staffMapper.getStoreManager(keyword);
    }

    @Override
    public Page<Staff> pageList(PageUtil pageUtil, Long storeId, Integer enabled, Integer role, String fullName, String pubPhone, String department) {
        QueryCondition condition = QueryCondition.createEmpty();
        if (storeId != null)
            condition.and(table.storeId.eq(storeId));
        if (enabled != null)
            condition.and(table.enabled.eq(enabled));
        if (role != null)
            condition.and(table.role.eq(role));
        if (StringUtils.isNotBlank(fullName))
            condition.and(table.fullName.like(fullName));
        if (StringUtils.isNotBlank(pubPhone))
            condition.and(table.pubPhone.like(pubPhone));

        QueryWrapper wrapper = QueryWrapper.create()
                .where(condition)
                .orderBy(table.id.desc());
        return getMapper().paginate(Page.of(pageUtil.getPage(), pageUtil.getRows()), wrapper);
    }

    @Override
    public List<Staff> getByUids(List<String> uidList) {
        return getMapper().selectListByCondition(table.uid.in(uidList));
    }

    @Override
    public List<Staff> listByCorpUidAndSaleNameIn(List<String> corpUidList, Set<String> saleNameList) {
        QueryCondition condition = table.corpUid.in(corpUidList)
                .and(table.fullName.in(saleNameList).or(table.nickName.in(saleNameList)))
                .and(table.enabled.eq(1));
        return getMapper().selectListByCondition(condition);
    }

    @Override
    public boolean updateEnabledByStoreUid(String storeUid, Integer enabled) {
        QueryWrapper wrapper = QueryWrapper.create()
                .select(staffRoles.staffUid)
                .from(staffRoles)
                .where(staffRoles.storeUid.eq(storeUid));

        return UpdateChain.of(Staff.class)
                .set(table.enabled, enabled)
                .where(table.uid.in(wrapper))
                .update();
    }

    @Override
    public Map<String, String> lastLoginTimeLog(List<String> corpUidList) {
        List<Staff> list = staffMapper.getLastLoginTime(corpUidList);

        Map<String, String> map = new HashMap<>();
        if (CollectionUtils.isNotEmpty(list)) {
            for (Staff staff : list) {
                map.put(staff.getCorpUid(), staff.getLastLoginTime());
            }
        }
        return map;
    }


    @Override
    public R<Object> pageList(PageUtil pageUtil, String storeUid, String keyword, Integer enabled) {
        QueryCondition condition = QueryCondition.createEmpty();
        if (enabled != null) {
            condition.and(table.enabled.eq(enabled));
        }
        if (StringUtils.isNotBlank(keyword)) {
            condition.and(table.fullName.like(keyword)
                    .or(table.nickName.like(keyword))
                    .or(table.username.like(keyword))
                    .or(table.priPhone.like(keyword))
                    .or(table.pubPhone.like(keyword))
            );
        }
        if (StringUtils.isNotBlank(storeUid)) {
            condition.and("B.store_uids like '%" + storeUid + "%'");
        }

        QueryWrapper staffRoleTable = QueryWrapper.create()
                .select(
                        staffRoles.staffUid,
                        QueryMethods.groupConcat(QueryMethods.distinct(staffRoles.storeUid)).as("store_uids")
                )
                .from(staffRoles)
                .groupBy(staffRoles.staffUid);

        QueryWrapper wrapper = QueryWrapper.create()
                .select(table.allColumns)
                .from(table)
                .leftJoin(staffRoleTable).as("B").on(table.uid.eq(QueryMethods.column("B.staff_uid")))
                .where(condition)
                .orderBy(table.id.desc(), table.enabled.desc());

        Page<StaffPageDto> page = getMapper().paginateWithRelationsAs(
                Page.of(pageUtil.getPage(), pageUtil.getRows()), wrapper, StaffPageDto.class
        );

        long totalRow = page.getTotalRow();
        List<StaffPageDto> list = page.getRecords();

        PageDto<StaffPageDto> pageDto = new PageDto<>();
        pageDto.setTotal(totalRow);
        pageDto.setList(list);
        return R.ok(pageDto);
    }


    @Override
    public R<Object> editStaffAndRole(
            String headStaffUid, String headStaffName, String storeUid, String staffUid,
            String fullName, String nickName, String pubPhone, String priPhone, String subjectType,
            String roleName, List<Integer> roleList, Integer isHeadquarterStaff, Integer isStoreStaff, Integer inStoreService
    ) {
        if (StringUtils.isBlank(storeUid)) {
            return R.fail("门店uid为空！");
        }
        if (StringUtils.isBlank(staffUid)) {
            return R.fail("所选员工uid为空！");
        }
        if (StringUtils.isBlank(roleName)) {
            return R.fail("请填写角色名称");
        }
        if (CollectionUtils.isEmpty(roleList)) {
            return R.fail("请选择角色");
        }
        // 员工是否是超管
        List<String> identifyList = roleStaffService.identifyListByStaffUid(headStaffUid);
        boolean superAdmin = AdminStaffRoleUtil.isSuperAdmin(identifyList);
        if (superAdmin) {
            if (isHeadquarterStaff == null) {
                return R.fail("请选择是否有管理界面！");
            }
            if (isStoreStaff == null) {
                return R.fail("请选择是否是门店员工！");
            }
            if (inStoreService == null) {
                return R.fail("请选择是否在门店代课！");
            }
        }

        boolean update = UpdateChain.of(Staff.class)
                .set(table.fullName, StringUtils.defaultString(fullName))
                .set(table.nickName, StringUtils.defaultString(nickName))
                .set(table.pubPhone, StringUtils.defaultString(pubPhone))
                .set(table.priPhone, StringUtils.defaultString(priPhone))
                .set(table.subjectType, StringUtils.defaultString(subjectType))
                .set(table.lastStaffUid, headStaffUid)
                .set(table.lastStaffName, headStaffName)
                .where(table.uid.eq(staffUid))
                .update();

        if (!update) {
            return R.fail("员工信息更新失败");
        }

        boolean b = staffRolesService.updateRoleBean(
                headStaffUid, headStaffName, storeUid, staffUid, roleName, roleList, superAdmin, isHeadquarterStaff, isStoreStaff, inStoreService
        );
        if (!b) {
            return R.fail("员工的角色信息更新失败");
        }

        return R.ok();
    }

}
